#include "ice_connection.h"
#include "ice/udp_port.h"

#include <rtc_base/logging.h>

namespace xrtc {

IceConnection::IceConnection(EventLoop *el, UDPPort *port, const Candidate &remote_candidate)
             : m_el(el), m_port(port), m_remote_candidate(remote_candidate) {
    
}

void IceConnection::on_read_packet(const char *buf, size_t len, int64_t ts) {
    // TODO
}

// 处理STUN Binding请求
void IceConnection::handle_stun_binding_request(StunMessage *stun_msg) {
    // role冲突
    // 发送binding response 
    send_stun_binding_response(stun_msg);
}

// 构建响应包，并调用 send_response_message 发送STUN Binding响应
void IceConnection::send_stun_binding_response(StunMessage *stun_msg) {
    const StunByteStringAttribute* username_attr = stun_msg->get_byte_string_attribute(STUN_ATTR_USERNAME);
    if (!username_attr) {
        RTC_LOG(LS_WARNING) << "send stun binding response error: no username";
        return;
    }

    // 构建STUN Binding响应消息
    StunMessage response_msg;
    response_msg.set_message_type(STUN_BINDING_RESPONSE);
    response_msg.set_transaction_id(stun_msg->get_transaction_id());
    response_msg.add_attribute(std::make_unique<StunXorAddressAttribute>(STUN_ATTR_XOR_MAPPED_ADDRESS, 
        get_remote_candidate().m_address));
    response_msg.add_message_integrity(m_port->get_ice_pwd());
    response_msg.add_fingerprint();

    send_response_message(response_msg);
}


// 发送响应消息
void IceConnection::send_response_message(const StunMessage &response) {
    const rtc::SocketAddress& addr = m_remote_candidate.m_address;

    rtc::ByteBufferWriter buf;
    if (!response.write(&buf)) {
        RTC_LOG(LS_WARNING) << "send response message error: write response message";
        return;
    }

    int ret = m_port->send_to(buf.Data(), buf.Length(), addr);
    if (ret < 0) {
        RTC_LOG(LS_WARNING) << to_string() << ": send "
            << stun_method_to_string(response.getMessageType())
            << " error, to=" << addr.ToString()
            << ", id=" << rtc::hex_encode(response.get_transaction_id());
        return;
    }

    RTC_LOG(LS_INFO) << to_string() << ": send "
            << stun_method_to_string(response.getMessageType())
            << " success, to=" << addr.ToString()
            << ", id=" << rtc::hex_encode(response.get_transaction_id());
}

std::string IceConnection::to_string() {
    std::stringstream ss;
    ss << "Conn[" << this << ":" << m_port->get_transport_name() 
        << ":" << m_port->get_component() 
        << ":" << m_port->get_local_addr().ToString()
        << "->" << m_remote_candidate.m_address.ToString();
    return ss.str();
}

} // namespace xrtc